import base64
import uuid
import asyncio
import aiohttp
import wave
import os
from aiohttp import ClientTimeout
from config import BYTEDANCE_SPEECH_CONFIG

appid = BYTEDANCE_SPEECH_CONFIG['APPID']
access_token = BYTEDANCE_SPEECH_CONFIG['ACCESS_TOKEN']
cluster = BYTEDANCE_SPEECH_CONFIG['CLUSTER']
voice_type = BYTEDANCE_SPEECH_CONFIG['VOICE_TYPE']

def process_text(text):
    sentences = [sentence.strip() + '.' for sentence in text.split('。') if sentence.strip()]
    return sentences

async def get_tts_async(session, text):
    host = "openspeech.bytedance.com"
    api_url = f"https://{host}/api/v1/tts"

    header = {"Authorization": f"Bearer;{access_token}"}

    request_json = {
        "app": {
            "appid": appid,
            "token": "access_token",
            "cluster": cluster
        },
        "user": {
            "uid": "388808087185088"
        },
        "audio": {
            "voice_type": voice_type,
            "encoding": "wav",
            "rate": 16000,
            "speed_ratio": 0,
            "volume_ratio": 1.0,
            "pitch_ratio": 1.0,
        },
        "request": {
            "reqid": str(uuid.uuid4()),
            "text": text,
            "text_type": "plain",
            "operation": "query",
            "with_frontend": 1,
            "frontend_type": "unitTson"

        }
    }

    retries = 10
    timeout = ClientTimeout(total=120)  # 增加超时时间到 120 秒
    for attempt in range(retries):
        try:
            async with session.post(api_url, json=request_json, headers=header, timeout=timeout) as resp:
                if resp.status == 200:
                    response_json = await resp.json()
                    if "data" in response_json:
                        data = response_json["data"]
                        return base64.b64decode(data)
                    else:
                        print(f"No 'data' field in response for text: {text}")
                else:
                    print(f"Request error: {resp.status}")
        except Exception as e:
            print(f"Attempt {attempt + 1} failed with error: {e}")
        await asyncio.sleep(3)  # 增加重试等待时间到 3 秒

    return b''

async def process_texts_async(texts):
       timeout = ClientTimeout(total=120)
       connector = aiohttp.TCPConnector(limit_per_host=2)  # 减少并发数量
       async with aiohttp.ClientSession(timeout=timeout, connector=connector) as session:
           tasks = [get_tts_async(session, text) for text in texts]
           return await asyncio.gather(*tasks)

def save_audio_chunk(audio_data, file_name):
    with open(file_name, "wb") as file:
        file.write(audio_data)

def concatenate_audio_files(audio_files, output_file):
    with wave.open(output_file, 'wb') as output:
        with wave.open(audio_files[0], 'rb') as first_file:
            output.setparams(first_file.getparams())
            for file_name in audio_files:
                with wave.open(file_name, 'rb') as wav_file:
                    output.writeframes(wav_file.readframes(wav_file.getnframes()))
    print(f"Audio file has been created: {output_file}")

    for file_name in audio_files:
        os.remove(file_name)
        print(f"Deleted temporary file: {file_name}")

async def main(long_text):
    sentences = process_text(long_text)
    async with aiohttp.ClientSession() as session:
        tasks = [get_tts_async(session, text) for text in sentences]
        audio_data_list = await asyncio.gather(*tasks)

    sentence_to_file = {}
    for sentence, audio_data in zip(sentences, audio_data_list):
        if audio_data:
            file_name = f"./audio/{uuid.uuid4().hex}.wav"
            save_audio_chunk(audio_data, file_name)
            sentence_to_file[sentence] = file_name
        else:
            print(f"No audio data returned for sentence: {sentence}")

    ordered_sentences = process_text(long_text)
    audio_files = [sentence_to_file.get(sentence) for sentence in ordered_sentences if sentence in sentence_to_file]

    if audio_files:
        concatenate_audio_files(audio_files, "./audio/temp_output.wav")
    else:
        print("No audio files were generated.")

if __name__ == "__main__":
    long_text = """从前有一只小老虎，它非常喜欢在森林里玩耍。有一天，它遇到了一只小兔子，小兔子非常可爱，小老虎立刻被它吸引住了。
                  小老虎决定和小兔子一起玩耍，它们一起跳过了小溪，穿过了森林，玩得非常开心。
                。"""
    asyncio.run(main(long_text))